/*
 * =============================================================
 *
 *        Project:  unp
 *
 *       Filename:  tcpserv04.c
 *
 *         Editor:  vim :set et ts=2 sts=2 sw=2
 *
 *         Author:  Martin Y. Yang , yang@libpix.org
 *
 *    Description:  
 *
 * =============================================================
 */

/**
 * @file
 * @brief Figure 5.12 Final(correct) version of TCP server that handles an error of EINTR from accept.
 */

#include "unp.h"

int tcpserv04_main(int argc, char *argv[])
{
  int listenfd, connfd;
  pid_t childpid;
  socklen_t clilen;
  struct sockaddr_in cliaddr, servaddr;
  void sig_chld(int);

  listenfd = Socket(AF_INET, SOCK_STREAM, 0);

  bzero(&servaddr, sizeof(servaddr));
  servaddr.sin_family = AF_INET;
  servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  servaddr.sin_port = htons(SERV_PORT);
  Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));
  Listen(listenfd, LISTENQ);
  Signal(SIGCHLD, sig_chld_unp);                    /* must call waitpid() */
  for ( ; ; ) {
    clilen = sizeof(cliaddr);
    if ((connfd = accept(listenfd, (SA *) & cliaddr, &clilen)) < 0) {
      if (errno == EINTR)
        continue;                               /* back to for() */
      else
        err_sys("accept error");
    }
    if ((childpid = Fork()) == 0) {             /* child process */
      Close(listenfd);                          /* close listening socket */
      str_echo_unp(connfd);                         /* process the request */
      exit(0);
      
    }
    Close(connfd);                              /* parent closes connected socket */
  }
}

